package com.by.toolkitspring.dubbo;

import com.google.common.collect.Maps;
import com.google.common.collect.Sets;
import lombok.extern.slf4j.Slf4j;
import org.apache.dubbo.common.threadpool.support.eager.EagerThreadPoolExecutor;
import org.dromara.dynamictp.adapter.dubbo.apache.ApacheDubboDtpAdapter;
import org.dromara.dynamictp.adapter.dubbo.apache.EagerThreadPoolExecutorProxy;
import org.dromara.dynamictp.common.entity.TpExecutorProps;
import org.dromara.dynamictp.core.support.ThreadPoolExecutorProxy;
import org.springframework.context.ApplicationEvent;
import org.springframework.stereotype.Component;

import java.util.Map;
import java.util.Set;
import java.util.concurrent.Executor;
import java.util.concurrent.ExecutorService;
import java.util.concurrent.ThreadPoolExecutor;

/**
 * @author Tian Wei
 * @version 1.0
 * @date 2024/2/19 6:41 PM
 */
@Component
@Slf4j
public class ByApacheDubboDtpAdapter extends ApacheDubboDtpAdapter {

    private static final String EXECUTOR_SERVICE_COMPONENT_KEY = ExecutorService.class.getName();

    private static final Map<String, TpExecutorProps> THREAD_POOL_NAME_CONFIG_MAP = Maps.newHashMap();

    private static final Set<String> PORT_LIST = Sets.newHashSet();

    @Override
    public void onApplicationEvent(ApplicationEvent event) {
//        if (event instanceof ServiceBeanExportedEvent) {
//            try {
//                DtpProperties dtpProperties = ApplicationContextHolder.getBean(DtpProperties.class);
//                THREAD_POOL_NAME_CONFIG_MAP.putAll(dtpProperties.getDubboTp().stream().collect(Collectors.toMap(TpExecutorProps::getThreadPoolName, Function.identity())));
//                initialize();
//                refresh(dtpProperties);
//
//                Map<String, ExecutorWrapper> executorWrappers = getExecutorWrappers();
//                for (String port : PORT_LIST) {
//                    String dubboServiceName = genTpName(port);
//                    ExecutorWrapper dubboTp = executorWrappers.get(dubboServiceName);
//                    if (Objects.isNull(dubboTp)) {
//                        return;
//                    }
//                    ExecutorAdapter<?> executor = dubboTp.getExecutor();
//                    if (Objects.isNull(executor)) {
//                        return;
//                    }
//                    ThreadPoolExecutor threadPoolExecutor = (ThreadPoolExecutor) executor.getOriginal();
//                    // 初始化所有核心线程
//                    int initThreadCount = threadPoolExecutor.prestartAllCoreThreads();
//                    log.info("[ByApacheDubboDtpAdapter][onApplicationEvent] dubboTpName:[{}] dubboTpServer:[{}] preStartAllCoreThreadsSuccess:[{}]", dubboServiceName, dubboTp.getThreadPoolAliasName(), initThreadCount);
//                }
//            } catch (Exception e) {
//                log.error("DynamicTp adapter, {} init failed.", getTpPrefix(), e);
//            }
//        }
    }

    @Override
    protected void initialize() {
//        ExecutorRepository executorRepository = ApplicationModel.defaultModel().getExtensionLoader(ExecutorRepository.class).getDefaultExtension();
//        ConcurrentMap<String, ConcurrentMap<String, ExecutorService>> data = (ConcurrentMap<String, ConcurrentMap<String, ExecutorService>>) ReflectionUtil.getFieldValue(
//                DefaultExecutorRepository.class, "data", executorRepository);
//        if (Objects.isNull(data)) {
//            return;
//        }
//        PORT_LIST.addAll(data.values().stream().map(Map::keySet).flatMap(Collection::stream).collect(Collectors.toSet()));
//        Map<String, ExecutorService> executorMap = data.get(EXECUTOR_SERVICE_COMPONENT_KEY);
//        if (MapUtils.isNotEmpty(executorMap)) {
//            executorMap.forEach((k, v) -> {
//                ThreadPoolExecutor proxy = getProxy(v);
//                executorMap.replace(k, proxy);
//                putAndFinalize(genTpName(k.toString()), v, proxy);
//            });
//        }
    }

    private ThreadPoolExecutor getProxy(Executor executor) {
        ThreadPoolExecutor proxy;
        if (executor instanceof EagerThreadPoolExecutor) {
            proxy = new EagerThreadPoolExecutorProxy((EagerThreadPoolExecutor) executor);
        } else {
            proxy = new ThreadPoolExecutorProxy((ThreadPoolExecutor) executor);
        }
        return proxy;
    }

    private String genTpName(String port) {
        return getTpPrefix() + "#" + port;
    }
}
